package com.sam.lib.store.sp;

import android.content.Context;
import android.content.SharedPreferences;

import com.sam.lib.store.IStore;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;


public class SharePreferenceStore implements IStore {

    private Map<String, SharedPreferences> storeMap = new HashMap<>();

    private static SharePreferenceStore mStore;

    private SharePreferenceStore() {

    }

    public static SharePreferenceStore getStore() {
        if (mStore == null) {
            synchronized (SharePreferenceStore.class) {
                if (mStore == null) {
                    mStore = new SharePreferenceStore();
                }
            }
        }
        return mStore;
    }

    public SharedPreferences getSharedPreferences(Context context, String name, int mode) {
        SharedPreferences target = storeMap.get(name);
        if (target == null) {
            target = context.getSharedPreferences(name, mode);
        }
        return target;
    }

    @Override
    public void putStringSet(Context context, String name, int mode, String key, Set<String> values) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putStringSet(key, values);
        editor.apply();
    }

    @Override
    public Set<String> getStringSet(Context context, String name, int mode, String key) {
        return getStringSet(context, name, mode, key, new HashSet<String>());
    }

    @Override
    public Set<String> getStringSet(Context context, String name, int mode, String key, Set<String> def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getStringSet(key, def);
    }

    @Override
    public void putString(Context context, String name, int mode, String key, String value) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putString(key, value);
        editor.apply();
    }

    @Override
    public String getString(Context context, String name, int mode, String key) {
        return getString(context, name, mode, key, "");
    }


    @Override
    public String getString(Context context, String name, int mode, String key, String def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getString(key, def);
    }

    @Override
    public void putLong(Context context, String name, int mode, String key, long value) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putLong(key, value);
        editor.apply();
    }

    @Override
    public long getLong(Context context, String name, int mode, String key) {
        return getLong(context, name, mode, key, 0L);
    }

    @Override
    public long getLong(Context context, String name, int mode, String key, long def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getLong(key, def);
    }

    @Override
    public void putFloat(Context context, String name, int mode, String key, float value) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putFloat(key, value);
        editor.apply();
    }

    @Override
    public float getFloat(Context context, String name, int mode, String key) {
        return getFloat(context, name, mode, key, 0.0f);
    }

    @Override
    public float getFloat(Context context, String name, int mode, String key, float def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getFloat(key, def);
    }

    @Override
    public void putInt(Context context, String name, int mode, String key, int value) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putInt(key, value);
        editor.apply();
    }

    @Override
    public int getInt(Context context, String name, int mode, String key) {
        return getInt(context, name, mode, key, 0);
    }

    @Override
    public int getInt(Context context, String name, int mode, String key, int def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getInt(key, def);
    }

    @Override
    public void putBoolean(Context context, String name, int mode, String key, boolean value) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        SharedPreferences.Editor editor = sp.edit();
        editor.putBoolean(key, value);
        editor.apply();
    }

    @Override
    public boolean getBoolean(Context context, String name, int mode, String key) {
        return getBoolean(context, name, mode, key, false);
    }

    @Override
    public boolean getBoolean(Context context, String name, int mode, String key, boolean def) {
        SharedPreferences sp = getSharedPreferences(context, name, mode);
        return sp.getBoolean(key, def);
    }

    @Override
    public void removeKey(Context context, String name, int mode, String key) {
        getSharedPreferences(context, name, mode).edit().remove(key).apply();
    }

    @Override
    public Map<String, ?> getAll(Context context, String name, int mode) {
        return getSharedPreferences(context, name, mode).getAll();
    }

    @Override
    public void clearAll(Context context, String name, int mode) {
        getSharedPreferences(context, name, mode).edit().clear().apply();
    }

    @Override
    public void saveAll(Context context, String name, int mode, Map<String, ?> data) {
        if (data != null && data.size() > 0) {
            SharedPreferences.Editor editor = getSharedPreferences(context, name, mode).edit();
            for (Map.Entry<String, ?> entry : data.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (value instanceof Integer) {
                    editor.putInt(key, (Integer) value);
                } else if (value instanceof Long) {
                    editor.putLong(key, (Long) value);
                } else if (value instanceof Float) {
                    editor.putFloat(key, (Float) value);
                } else if (value instanceof String) {
                    editor.putString(key, (String) value);
                } else if (value instanceof Boolean) {
                    editor.putBoolean(key, (Boolean) value);
                } else if (value instanceof Set) {
                    editor.putStringSet(key, (Set) value);
                }
            }
            editor.apply();
        }

    }

    public final static String KEY_IS_MIGRATE = "_is_migrate";

    @Override
    public void migrate(Context context, String toName, int toMode, IStore fromStore, String fromName, int fromMode) {
        if (context != null) {
            SharedPreferences sp = context.getSharedPreferences(toName, toMode);
            if (!sp.getBoolean(KEY_IS_MIGRATE, false)) {
                Map<String, ?> map = fromStore.getAll(context, fromName, fromMode);
                migrateToSharePreference(sp, map);
                sp.edit().putBoolean(KEY_IS_MIGRATE, true).apply();
                fromStore.clearAll(context, fromName, fromMode);
            }
        }
    }

    private static void migrateToSharePreference(SharedPreferences sp, Map<String, ?> map) {
        if (map != null && map.size() > 0 && sp != null) {
            SharedPreferences.Editor editor = sp.edit();
            for (Map.Entry<String, ?> entry : map.entrySet()) {
                String key = entry.getKey();
                Object value = entry.getValue();
                if (value instanceof String) {
                    editor.putString(key, (String) value);
                } else if (value instanceof Integer) {
                    editor.putInt(key, (Integer) value);
                } else if (value instanceof Long) {
                    editor.putLong(key, (Long) value);
                } else if (value instanceof Float) {
                    editor.putFloat(key, (Float) value);
                } else if (value instanceof Boolean) {
                    editor.putBoolean(key, (Boolean) value);
                } else if (value instanceof Set) {
                    editor.putStringSet(key, (Set) value);
                }
            }
            editor.apply();
        }
    }


}
